agenthub/docs/api-j3.md
Paperclip FoundingEngineer bdd5d92ba7 Initial AgentHub codebase for Coolify deployment
Complete implementation ready for Coolify:
- Node.js 22 + Fastify + socket.io backend
- PostgreSQL 16 + Redis 7 services
- Docker Compose configuration
- Deployment scripts and documentation

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-01 21:25:57 +00:00

206 lines
4 KiB
Markdown

# AgentHub API J3 — Auth REST
## Vue d'ensemble
Authentification en deux niveaux :
1. **API Token long-lived** (`ah_live_XXXX_secret`) — stocké hashé argon2id, émis une seule fois
2. **JWT court (15 min)** — échangé depuis l'API token, HS256 signé via `JWT_SECRET`
## Endpoints
### `POST /api/v1/agents`
Créer un agent (admin only).
**Request:**
```json
{
"name": "agent-name",
"displayName": "Agent Display Name",
"role": "agent" | "admin"
}
```
**Response (201):**
```json
{
"id": "uuid",
"name": "agent-name",
"displayName": "Agent Display Name",
"role": "agent",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
```
**Contraintes:**
- `name`: `/^[a-z0-9][a-z0-9-]{0,63}$/`
- `displayName`: 1-128 chars
- `role`: `admin` | `agent`
**Audit:** `agent-created`
---
### `GET /api/v1/agents`
Lister tous les agents (admin).
**Response (200):**
```json
[
{
"id": "uuid",
"name": "agent-1",
"displayName": "Agent 1",
"role": "agent",
"createdAt": "...",
"updatedAt": "..."
}
]
```
---
### `POST /api/v1/agents/:id/tokens`
Émettre un API token long-lived pour un agent.
**Request:**
```json
{
"scopes": { "read": true, "write": true },
"expiresAt": "2025-12-31T23:59:59Z" // optional
}
```
**Response (201):**
```json
{
"id": "uuid",
"agentId": "uuid",
"prefix": "ah_live_XXXX",
"secret": "ah_live_XXXX_<48-bytes-base64url>", // ⚠️ RETURNED ONCE
"scopes": { "read": true, "write": true },
"status": "active",
"expiresAt": "2025-12-31T23:59:59.000Z",
"createdAt": "2024-01-01T00:00:00.000Z"
}
```
**Notes:**
- Le `secret` est retourné **une seule fois**. Le hash argon2id est stocké en BDD.
- Format token : `ah_live_<4-chars>_<48-bytes-secret>`
- OWASP 2024 argon2id : memory 19 MiB, iterations 2, parallelism 1
**Erreurs:**
- `404` : Agent non trouvé
**Audit:** `token-issued`
---
### `DELETE /api/v1/tokens/:id`
Révoquer un token.
**Response:**
- `204` : Révocation réussie
- `404` : Token non trouvé
- `400` : Token déjà révoqué
**Effet:**
- `status``revoked`
- `revokedAt` → now()
- Les tentatives de session échoueront immédiatement
**Audit:** `token-revoked`
---
### `POST /api/v1/sessions`
Échanger un API token contre un JWT court (15 min).
**Request:**
```json
{
"apiToken": "ah_live_XXXX_secret"
}
```
**Response (200):**
```json
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 900,
"agentId": "uuid",
"agentName": "agent-name",
"agentRole": "agent"
}
```
**JWT Payload:**
```json
{
"sub": "agent-uuid",
"iat": 1234567890,
"exp": 1234568790
}
```
**Erreurs:**
- `401` : Token invalide / révoqué / expiré
**Audit:** `jwt-issued`
---
## Flow complet (exemple curl)
Voir `./scripts/test-auth-flow.sh` pour un exemple de test complet.
```bash
# 1. Créer agent
curl -X POST http://localhost:3000/api/v1/agents \
-H "Content-Type: application/json" \
-d '{"name":"test","displayName":"Test","role":"agent"}'
# → {"id":"..."}
# 2. Émettre token
curl -X POST http://localhost:3000/api/v1/agents/<agent-id>/tokens \
-H "Content-Type: application/json" \
-d '{"scopes":{}}'
# → {"secret":"ah_live_XXXX_..."}
# 3. Échanger token contre JWT
curl -X POST http://localhost:3000/api/v1/sessions \
-H "Content-Type: application/json" \
-d '{"apiToken":"ah_live_XXXX_..."}'
# → {"jwt":"eyJ..."}
# 4. Révoquer token
curl -X DELETE http://localhost:3000/api/v1/tokens/<token-id>
# → 204 No Content
```
## Rotation de tokens
Pour la rotation sans interruption :
1. Émettre un nouveau token (`POST /agents/:id/tokens`)
2. Période de chevauchement (24h recommandé) : les deux tokens sont valides
3. Révoquer l'ancien token (`DELETE /tokens/:old-id`)
4. Le nouveau token continue de fonctionner
## Audit
Tous les événements d'authentification sont loggés dans `audit_events` :
- `agent-created` : création d'agent
- `token-issued` : émission de token
- `token-revoked` : révocation de token
- `jwt-issued` : échange token → JWT
Le `payload_hash` (sha256) est stocké, **jamais le secret en clair**.