Date ajout : 24/01/2026 Priorité : HAUTE Catégorie : DEV / INFRA Statut : À FAIRE Effort estimé : M (1-2 semaines) Bloque : qwik-interface-generator
Marre de configurer l'auth pour chaque projet. On a besoin d'un service centralisé qui gère :
/api/linkedin/auth → OAuth LinkedIn
/api/linkedin/callback → Callback OAuth
/api/linkedin/profile → Get profile
/api/linkedin/post → Créer post
/api/linkedin/* → Scraping Playwright
/api/gmail/* → Scraping Playwright
┌─────────────────────────────────────────────────────────────────────┐
│ CONNECTORS HUB │
│ (connectors-api v2) │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ REGISTRY │ │
│ │ GET /api/connectors → Liste tous les connecteurs│ │
│ │ GET /api/connectors/:id → Détails + status │ │
│ │ POST /api/connectors → Ajouter connecteur custom │ │
│ │ DEL /api/connectors/:id → Supprimer │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ AUTH │ │
│ │ GET /api/connectors/:id/auth → URL OAuth ou instructions │ │
│ │ GET /api/connectors/:id/callback → Callback OAuth │ │
│ │ POST /api/connectors/:id/token → Set API Key / Bearer │ │
│ │ DEL /api/connectors/:id/auth → Révoquer auth │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ PROXY FETCH (le cœur du système) │ │
│ │ POST /api/fetch │ │
│ │ { │ │
│ │ "connector": "stripe", // ou "my-custom-api" │ │
│ │ "method": "GET", │ │
│ │ "path": "/v1/customers", │ │
│ │ "params": { "limit": 10 }, │ │
│ │ "body": { ... } // pour POST/PUT │ │
│ │ } │ │
│ │ → Injecte auth automatiquement │ │
│ │ → Fait la requête │ │
│ │ → Retourne la réponse │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ SWAGGER IMPORT │ │
│ │ POST /api/connectors/import/swagger │ │
│ │ → Upload swagger.json │ │
│ │ → Crée connecteur auto-configuré (base_url, endpoints) │ │
│ │ → Retourne config pour auth manuelle │ │
│ └────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
CREATE TABLE connectors.config (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL UNIQUE, -- "stripe", "github", "my-api"
display_name TEXT, -- "Stripe Payments"
base_url TEXT NOT NULL, -- "https://api.stripe.com"
-- Auth config
auth_type TEXT NOT NULL, -- "oauth2", "api_key", "bearer", "basic"
auth_config JSONB DEFAULT '{}', -- OAuth: client_id, scopes, etc.
-- Swagger/OpenAPI (optionnel)
swagger_url TEXT, -- URL du swagger
swagger_spec JSONB, -- Spec cachée
-- Metadata
icon_url TEXT,
description TEXT,
is_builtin BOOLEAN DEFAULT false, -- true pour LinkedIn, Stripe, etc.
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE connectors.tokens (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
connector_id UUID REFERENCES connectors.config(id) ON DELETE CASCADE,
user_id UUID, -- Pour multi-tenant (null = global)
-- Tokens
access_token TEXT,
refresh_token TEXT,
api_key TEXT, -- Pour auth_type = api_key
-- Metadata
expires_at TIMESTAMPTZ,
scopes TEXT[],
token_metadata JSONB DEFAULT '{}', -- Infos supplémentaires
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(connector_id, user_id)
);
| Type | Config | Injection Header |
|---|---|---|
api_key |
{ header: "X-API-Key" } |
X-API-Key: {token} |
bearer |
- | Authorization: Bearer {token} |
basic |
- | Authorization: Basic {base64} |
oauth2 |
{ client_id, client_secret, scopes, auth_url, token_url } |
Authorization: Bearer {token} |
custom |
{ header, prefix } |
{header}: {prefix} {token} |
| Connecteur | Auth Type | Base URL | Priorité | Notes |
|---|---|---|---|---|
| oauth2 | api.linkedin.com | ✅ Legacy | Garder le code existant, migrer vers nouveau système | |
| github | oauth2 | api.github.com | P1 | GitLab API similaire |
| o2switch | api_key/basic | ? | P1 | Hébergement, besoin réel |
| mailjet | api_key | api.mailjet.com | P1 | Emails transactionnels |
| supabase | api_key | {project}.supabase.co | P1 | BDD + Auth |
| stripe | api_key | api.stripe.com | P2 | Paiements (plus tard) |
| openai | bearer | api.openai.com | P3 | Fallback IA (Ollama prioritaire) |
□ Créer schema Supabase (connectors.config, connectors.tokens)
□ Interface TypeScript Connector
□ Migrer LinkedIn vers nouveau système
□ Endpoint GET /api/connectors (liste)
□ Endpoint GET /api/connectors/:id/status
□ Persistance tokens en DB
□ Endpoint POST /api/fetch
□ Résolution connector → config
□ Injection auth automatique
□ Gestion erreurs (401 → refresh token)
□ Logging des requêtes
□ GitHub (oauth2) - accès repos, issues, API
□ O2switch (api_key/basic) - gestion hébergement
□ Mailjet (api_key) - envoi emails
□ Supabase (api_key) - BDD directe
□ Generic REST (configurable) - pour tout le reste
□ Generic OAuth2 (configurable)
□ Stripe (api_key) - paiements
□ OpenAI (bearer) - fallback IA
□ Endpoint POST /api/connectors/import/swagger
□ Parser swagger → base_url, endpoints
□ Auto-detect auth type depuis swagger security
□ Génération config connecteur
// Avant (dans chaque projet)
const stripe = new Stripe(process.env.STRIPE_KEY);
const res = await stripe.customers.list({ limit: 10 });
// Après (via Connectors Hub)
const res = await fetch('http://connectors:5400/api/fetch', {
method: 'POST',
body: JSON.stringify({
connector: 'stripe',
method: 'GET',
path: '/v1/customers',
params: { limit: 10 }
})
});
// Auth injectée automatiquement, token géré par le hub
// Connecteur custom depuis Swagger
await fetch('http://connectors:5400/api/connectors/import/swagger', {
method: 'POST',
body: JSON.stringify({
name: 'petstore',
swagger_url: 'https://petstore.swagger.io/v2/swagger.json'
})
});
// Puis utilisation immédiate
await fetch('http://connectors:5400/api/fetch', {
method: 'POST',
body: JSON.stringify({
connector: 'petstore',
method: 'GET',
path: '/pet/findByStatus',
params: { status: 'available' }
})
});